package com.lenovo.dil.tiltbaseddemo;

import java.util.List;
import java.util.Observable;
import java.util.Observer;
import java.util.Random;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.lenovo.dil.tiltbaseddemo.model.AppInfo;
import com.lenovo.dil.tiltbaseddemo.model.ItemInfo;
import com.lenovo.dil.tiltbaseddemo.sensor.SensorsProcess;
import com.lenovo.dil.tiltbaseddemo.utils.PreferenceUtil;

public class MainActivity extends FragmentActivity {

	final static int ICON_SIZE = 72;
	final static int SIDE_MARGIN = 10;

	static int SCREEN_WIDTH;
	static int SCREEN_HEIGHT;

	static List<AppInfo> appInfoList = null;

	public static MainActivity mActivity;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		mActivity = this;
		PreferenceUtil.init(this);
		setContentView(R.layout.activity_main);
		appInfoList = AppInfo.queryAppInfo(this);
		System.out.println(appInfoList.size());
		DisplayMetrics dm = new DisplayMetrics();
		this.getWindowManager().getDefaultDisplay().getMetrics(dm);
		SCREEN_WIDTH = dm.widthPixels;
		SCREEN_HEIGHT = dm.heightPixels;
		if (savedInstanceState == null) {
			PlaceholderFragment fragment = new PlaceholderFragment();
			getSupportFragmentManager().beginTransaction()
					.add(R.id.container, fragment).commit();
			SensorsProcess.getInstance().addObserver(fragment);
		}
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		menu.add(Menu.NONE, Menu.FIRST, 1, "设置");
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		if (item.getItemId() == Menu.FIRST) {
			startActivity(new Intent(this, SettingsActivity.class));
			return true;
		}
		return super.onOptionsItemSelected(item);
	}

	/**
	 * A placeholder fragment containing a simple view.
	 */
	public static class PlaceholderFragment extends Fragment implements
			Observer, OnClickListener, OnTouchListener {

		RelativeLayout rootView;

		Button btnStartEnd;// , btnAdsorp;
		FrameLayout contentLayout = null;
		LinearLayout[] layouts = new LinearLayout[20];
		ImageView ball;
		boolean isStart;
		int statusBarHeight = 0;

		long lastTimeStamp = 0;

		Handler mHandler = new Handler();
		LinearLayout mFocusLayout = null;
		long mLostFocusTime = Long.MAX_VALUE;

		View dividers[] = new View[5];
		int[][] dividerLocations = null;

		TextView mAngleView;

		public PlaceholderFragment() {
		}

		@Override
		public void onCreate(Bundle savedInstanceState) {
			super.onCreate(savedInstanceState);
			statusBarHeight = getStatusBarHeight();
		}

		@Override
		public View onCreateView(LayoutInflater inflater, ViewGroup container,
				Bundle savedInstanceState) {
			View rootView = inflater.inflate(R.layout.fragment_main, container,
					false);
			rootView.setOnTouchListener(this);
			mAngleView = (TextView) rootView.findViewById(R.id.angle);
			btnStartEnd = (Button) rootView.findViewById(R.id.btn_start_end);
			// btnAdsorp = (Button) rootView.findViewById(R.id.btn_adsorp);
			btnStartEnd.setOnClickListener(this);
			// btnAdsorp.setOnClickListener(this);
			contentLayout = (FrameLayout) rootView
					.findViewById(R.id.content_layout);
			ball = (ImageView) rootView.findViewById(R.id.indicator_ball);
			layouts[0] = (LinearLayout) rootView.findViewById(R.id.item1);
			layouts[1] = (LinearLayout) rootView.findViewById(R.id.item2);
			layouts[2] = (LinearLayout) rootView.findViewById(R.id.item3);
			layouts[3] = (LinearLayout) rootView.findViewById(R.id.item4);
			layouts[4] = (LinearLayout) rootView.findViewById(R.id.item5);
			layouts[5] = (LinearLayout) rootView.findViewById(R.id.item6);
			layouts[6] = (LinearLayout) rootView.findViewById(R.id.item7);
			layouts[7] = (LinearLayout) rootView.findViewById(R.id.item8);
			layouts[8] = (LinearLayout) rootView.findViewById(R.id.item9);
			layouts[9] = (LinearLayout) rootView.findViewById(R.id.item10);
			layouts[10] = (LinearLayout) rootView.findViewById(R.id.item11);
			layouts[11] = (LinearLayout) rootView.findViewById(R.id.item12);
			layouts[12] = (LinearLayout) rootView.findViewById(R.id.item13);
			layouts[13] = (LinearLayout) rootView.findViewById(R.id.item14);
			layouts[14] = (LinearLayout) rootView.findViewById(R.id.item15);
			layouts[15] = (LinearLayout) rootView.findViewById(R.id.item16);
			layouts[16] = (LinearLayout) rootView.findViewById(R.id.item17);
			layouts[17] = (LinearLayout) rootView.findViewById(R.id.item18);
			layouts[18] = (LinearLayout) rootView.findViewById(R.id.item19);
			layouts[19] = (LinearLayout) rootView.findViewById(R.id.item20);

			dividers[0] = rootView.findViewById(R.id.divider1);
			dividers[1] = rootView.findViewById(R.id.divider2);
			dividers[2] = rootView.findViewById(R.id.divider3);
			dividers[3] = rootView.findViewById(R.id.divider4);
			dividers[4] = rootView.findViewById(R.id.divider5);

			int i = 0;
			Random r = new Random();
			int rs[] = { r.nextInt(4), 4 + r.nextInt(4), 8 + r.nextInt(4),
					12 + r.nextInt(4), 16 + r.nextInt(4) };
			if (appInfoList != null && appInfoList.size() > 0) {
				for (; i < 20 && i < appInfoList.size(); i++) {
					ItemInfo item = new ItemInfo(getActivity(), layouts[i],
							appInfoList.get(i));
					item.setSelected(false);
					if (i == rs[i / 4] || i == 9 || i == 10) {
						layouts[i].setVisibility(View.INVISIBLE);
					}
					layouts[i].setTag(item);
				}
			}
			for (; i < 20; i++) {
				layouts[i].setVisibility(View.INVISIBLE);
			}
			return rootView;
		}

		@Override
		public void onClick(View v) {
			if (v.getId() == R.id.btn_start_end) {
				if (!isStart) {
					SensorsProcess.getInstance().registerSensor();
					btnStartEnd.setText("停止");
					// btnAdsorp.setVisibility(View.VISIBLE);
					initDivider();
				} else {
					SensorsProcess.getInstance().unRegisterSensor();
					btnStartEnd.setText("开始");
					// btnAdsorp.setVisibility(View.GONE);
					mAngleView.setText(String.format("pitch=%d,roll=%d", 0, 0));
					hideDivider();
				}
				isStart = !isStart;
				lastSensorData = null;
				getActivity().runOnUiThread(new Runnable() {

					@Override
					public void run() {
						for (LinearLayout layout : layouts) {
							if (layout.getVisibility() != View.VISIBLE) {
								continue;
							}
							ItemInfo itemInfo = (ItemInfo) layout.getTag();
							if (itemInfo != null) {
								itemInfo.setSelected(false);
							}
						}
						FrameLayout.LayoutParams param = (FrameLayout.LayoutParams) ball
								.getLayoutParams();
						if (isStart) {
							param.gravity = Gravity.LEFT | Gravity.TOP;
							param.leftMargin = contentLayout.getWidth() / 2;
							param.topMargin = contentLayout.getHeight() / 2;
						} else {
							param.gravity = Gravity.CENTER;
							param.leftMargin = 0;
							param.topMargin = 0;
						}
						ball.requestLayout();
					}
				});
			} else {
				int x = ball.getLeft() + ball.getWidth() / 2;
				int y = ball.getTop() + ball.getHeight();
				final LinearLayout layout = getInLayout(x, y);
				if (layout != null) {
					final ItemInfo itemInfo = (ItemInfo) layout.getTag();
					SensorsProcess.getInstance().unRegisterSensor();
					itemInfo.setClicked();
					isStart = false;
					btnStartEnd.setText("开始");
					// btnAdsorp.setVisibility(View.GONE);
					mAngleView.setText(String.format("pitch=%d,roll=%d", 0, 0));
				}
			}
		}

		float[] lastSensorData = null;

		long mLastPitchTime = Long.MAX_VALUE;
		boolean mPitchEnabled = false;

		@Override
		public void update(Observable observable, Object data) {
			System.out.println("update");
			final float[] tmp = (float[]) data;
			if (lastSensorData == null) {
				lastSensorData = tmp;
				lastTimeStamp = System.currentTimeMillis();
			}
			if (Math.abs(tmp[1] - lastSensorData[1]) < .5
					&& Math.abs(tmp[2] - lastSensorData[2]) < .5) {
				return;
			}
			getActivity().runOnUiThread(new Runnable() {

				@Override
				public void run() {
					mAngleView.setText(String.format("pitch=%d,roll=%d",
							(int) tmp[1], (int) tmp[2]));
				}
			});
			if (mPitchEnabled
					&& (tmp[1] < -PreferenceUtil.get_move_up_init_angle() || tmp[1] > PreferenceUtil
							.get_move_down_init_angle())) {
				if (mLastPitchTime == Long.MAX_VALUE) {
					mLastPitchTime = System.currentTimeMillis();
				} else {
					if (System.currentTimeMillis() - mLastPitchTime >= PreferenceUtil
							.get_move_up_down_time_delay()) {
						mLastPitchTime = Long.MAX_VALUE;
						mPitchEnabled = false;
						if (tmp[1] > 0) {
							mDividerIndex += 1;
							if (mDividerIndex >= dividers.length) {
								mDividerIndex = dividers.length - 1;
							}
						} else {
							mDividerIndex -= 1;
							if (mDividerIndex < 0) {
								mDividerIndex = 0;
							}
						}
						getActivity().runOnUiThread(new Runnable() {

							@Override
							public void run() {
								showDivider();
							}
						});
					}
				}
			} else if (tmp[1] < -PreferenceUtil.get_move_up_init_angle()
					|| tmp[1] > PreferenceUtil.get_move_down_init_angle()) {
				mHandler.postDelayed(new Runnable() {

					@Override
					public void run() {
						mPitchEnabled = true;
						mLastPitchTime = Long.MAX_VALUE;
					}
				}, PreferenceUtil.get_move_up_down_time_delay());
			}
			int x = ball.getLeft() + ball.getWidth() / 2;
			int y = ball.getTop() + ball.getHeight();
			final LinearLayout layout = getInLayout(x, y);
			double tiltMag = Math.sqrt(tmp[1] * tmp[1] + tmp[2] * tmp[2]);
			double tiltAngle = Math.asin(tmp[2] / tiltMag) * 180 / Math.PI;
			int tiltGain = getTiltGainByTiltAngle(tiltAngle);
			double speed = tiltGain * Math.abs(tiltMag)
					* getSpeedRatio(layout, x);
			double dBall = speed * (System.currentTimeMillis() - lastTimeStamp)
					/ 1000;
			FrameLayout.LayoutParams param = (FrameLayout.LayoutParams) ball
					.getLayoutParams();
			param.leftMargin += dBall * Math.sin(tiltAngle * Math.PI / 180);
			param.topMargin += (tmp[1] > 0 ? 1 : -1) * dBall
					* Math.cos(tiltAngle * Math.PI / 180);
			if (tmp[1] > 0) {
				if (param.topMargin > dividerLocations[mDividerIndex == -1 ? 2
						: mDividerIndex][1]) {
					param.topMargin = dividerLocations[mDividerIndex == -1 ? 2
							: mDividerIndex][1];
				}
			}
			if (tmp[1] < 0) {
				if (param.topMargin < dividerLocations[mDividerIndex == -1 ? 2
						: mDividerIndex][1]) {
					param.topMargin = dividerLocations[mDividerIndex == -1 ? 2
							: mDividerIndex][1];
				}
			}
			if (param.leftMargin <= 0) {
				param.leftMargin = 0;
			}
			if (param.leftMargin >= SCREEN_WIDTH - ball.getWidth()) {
				param.leftMargin = SCREEN_WIDTH - ball.getWidth();
			}
			if (param.topMargin <= 0) {
				param.topMargin = 0;
			}
			if (param.topMargin >= contentLayout.getHeight() - ball.getHeight()) {
				param.topMargin = contentLayout.getHeight() - ball.getHeight();
			}
			if (getActivity() != null) {
				getActivity().runOnUiThread(new Runnable() {

					@Override
					public void run() {
						ball.requestLayout();
						for (LinearLayout layout : layouts) {
							if (layout.getVisibility() != View.VISIBLE) {
								continue;
							}
							if (mFocusLayout != layout) {
								ItemInfo itemInfo = (ItemInfo) layout.getTag();
								if (itemInfo != null) {
									itemInfo.setSelected(false);
								}
							}
						}
						if (layout != null) {
							final ItemInfo itemInfo = (ItemInfo) layout
									.getTag();
							if (itemInfo != null) {
								itemInfo.setSelected(true);
								if (mFocusLayout != layout) {
									mHandler.postDelayed(new Runnable() {

										@Override
										public void run() {
											if (mFocusLayout != null
													&& mFocusLayout.getTag() == itemInfo
													&& System
															.currentTimeMillis()
															- mLostFocusTime > PreferenceUtil
																.get_select_app_time_delay()) {
												SensorsProcess.getInstance()
														.unRegisterSensor();
												itemInfo.setClicked();
												isStart = false;
												btnStartEnd.setText("开始");
												// btnAdsorp
												// .setVisibility(View.GONE);
												mAngleView
														.setText(String
																.format("pitch=%d,roll=%d",
																		0, 0));
											}
										}
									}, PreferenceUtil
											.get_select_app_time_delay());
								}
							}
						} else {
							mLostFocusTime = System.currentTimeMillis();
						}
						mFocusLayout = layout;
						// showDivider();
					}
				});
			}
			lastSensorData = tmp;
			lastTimeStamp = System.currentTimeMillis();
		}

		int getTiltGainByTiltAngle(double tiltAngle) {
			return PreferenceUtil.get_tilt_gain();
		}

		@Override
		public void onAttach(Activity activity) {
			super.onAttach(activity);
		}

		@Override
		public void onDetach() {
			super.onDetach();
			SensorsProcess.getInstance().unRegisterSensor();
			SensorsProcess.getInstance().deleteObserver(this);
		}

		int getStatusBarHeight() {
			Class<?> c = null;
			Object obj = null;
			java.lang.reflect.Field field = null;
			int x = 0;
			int statusBarHeight = 0;
			try {
				c = Class.forName("com.android.internal.R$dimen");
				obj = c.newInstance();
				field = c.getField("status_bar_height");
				x = Integer.parseInt(field.get(obj).toString());
				statusBarHeight = getResources().getDimensionPixelSize(x);
				return statusBarHeight;
			} catch (Exception e) {
				e.printStackTrace();
			}
			return statusBarHeight;
		}

		LinearLayout getInLayout(int x, int y) {
			for (LinearLayout layout : layouts) {
				if (layout.getVisibility() != View.VISIBLE) {
					continue;
				}
				ItemInfo itemInfo = (ItemInfo) layout.getTag();
				int location[] = itemInfo.getIconLeftTop();
				if (itemInfo != null) {
					if (x >= location[0]
							&& x <= location[0] + itemInfo.getIconWidth()
							&& y >= location[1] - statusBarHeight
							&& y <= location[1] - statusBarHeight
									+ itemInfo.getIconHeight()) {
						return layout;
					}
				}
			}
			return null;
		}

		int mDividerIndex = -1;

		void initDivider() {
			mDividerIndex = -1;
			int y = ball.getTop();
			if (dividerLocations == null) {
				dividerLocations = new int[5][2];
				for (int i = 0; i < dividers.length; i++) {
					final int[] location = new int[2];
					dividers[i].getLocationOnScreen(location);
					location[1] = location[1] - statusBarHeight;
					dividerLocations[i] = location;
				}
			}
			for (int i = 0; i < dividers.length; i++) {
				dividers[i].setVisibility(View.GONE);
			}
			for (int i = 0; i < dividerLocations.length - 1; i++) {
				if (y > dividerLocations[i][1]
						&& y < dividerLocations[i + 1][1]) {
					mDividerIndex = i;
					break;
				}
			}
			if (mDividerIndex == -1) {
				mDividerIndex = 2;
			}
			dividers[mDividerIndex].setVisibility(View.VISIBLE);
		}

		void showDivider() {
			for (int i = 0; i < dividers.length; i++) {
				dividers[i].setVisibility(View.GONE);
			}
			if (mDividerIndex != -1) {
				dividers[mDividerIndex].setVisibility(View.VISIBLE);
			}
		}

		void hideDivider() {
			if (mDividerIndex != -1) {
				dividers[mDividerIndex].setVisibility(View.GONE);
				mDividerIndex = -1;
			}
		}

		float getSpeedRatio(View overIcon, int x) {
			float ratio = PreferenceUtil.get_over_icon_speed_ratio();
			if (ratio > 1) {
				return (float) Math.abs(Math
						.cos(x * Math.PI / SCREEN_WIDTH / 4));
			} else if (overIcon == null) {
				return 1;
			}
			return ratio;
		}

		float downX, downY;

		@Override
		public boolean onTouch(View v, MotionEvent event) {
			if (SensorsProcess.registerState) {
				switch (event.getAction()) {
				case MotionEvent.ACTION_DOWN:
					downX = event.getX();
					downY = event.getY();
					break;
				case MotionEvent.ACTION_UP:
					float delta = event.getY() - downY;
					System.out.println("onTouch:" + delta);
					if (Math.abs(delta) > 50) {
						mDividerIndex = (mDividerIndex + (delta < 0 ? -1 : 1) + 5) % 5;
						showDivider();
					} else {
						int x = ball.getLeft() + ball.getWidth() / 2;
						int y = ball.getTop() + ball.getHeight();
						final LinearLayout layout = getInLayout(x, y);
						if (layout != null) {
							if (SensorsProcess.registerState) {
								final ItemInfo itemInfo = (ItemInfo) layout
										.getTag();
								SensorsProcess.getInstance().unRegisterSensor();
								itemInfo.setClicked();
								isStart = false;
								btnStartEnd.setText("开始");
								// btnAdsorp.setVisibility(View.GONE);
								mAngleView.setText(String.format(
										"pitch=%d,roll=%d", 0, 0));
							}
						}
					}
					break;
				default:
					break;
				}
				return true;
			}
			if (event.getAction() == MotionEvent.ACTION_UP
					&& dividerLocations != null) {
				if (mFocusLayout != null) {
					ItemInfo itemInfo = (ItemInfo) mFocusLayout.getTag();
					if (itemInfo != null) {
						itemInfo.setSelected(false);
					}
				}
				mFocusLayout = null;
				mLostFocusTime = System.currentTimeMillis();
				SensorsProcess.getInstance().registerSensor();
				return true;
			}
			return true;
		}
	}

}
